﻿using System;
using System.Collections.Generic;
using System.Text;

namespace MPMovieCatalog.Util
{
    public class Fields
    {
        public static Field Title = new SimpleField("title");
        public static Field Tagline = new SimpleField("tagline");
        public static Field Director = new SimpleField("director");
        public static Field Writer = new SimpleField("writer");
        public static Field Year = new SimpleField("year");
        public static Field Runtime = new SimpleField("runtime", string.Format("##### '{0}';;#", ResourceUtils.GetString("template", "runtimeUnit")));
        public static Field Watched = new BooleanField("isWatched");
        public static Field IMDBRating = new SimpleField("imdbRating");
        public static Field IMDBNumber = new SimpleField("imdbNumber");
        public static Field IMDBVotes = new SimpleField("imdbVotes");
        public static Field MPAARating = new SimpleField("mpaaRating");
        public static Field Description = new SimpleField("description");
        public static Field Genres = new ListField("genres", "genre");
        public static Field Actors = new ListField("actors", "actor");
        public static Field Files = new ListField("files", "file");

        private static List<Field> m_fields = null;

        public static List<Field> GetFields()
        {
            if (m_fields == null)
            {
                m_fields = new List<Field>();
                m_fields.Add(Title);
                m_fields.Add(Tagline);
                m_fields.Add(Director);
                m_fields.Add(Writer);
                m_fields.Add(Year);
                m_fields.Add(Runtime);
                m_fields.Add(Watched);
                m_fields.Add(IMDBRating);
                m_fields.Add(IMDBNumber);
                m_fields.Add(IMDBVotes);
                m_fields.Add(MPAARating);
                m_fields.Add(Description);
                m_fields.Add(Genres);
                m_fields.Add(Actors);
                m_fields.Add(Files);
            }

            return m_fields;
        }

        public static Field FindFieldByName(string name)
        {
            Field field = null;
            List<Field> fields = GetFields();
            foreach (Field f in fields)
            {
                if (f.Name.Equals(name, StringComparison.OrdinalIgnoreCase))
                {
                    field = f;
                    break;
                }
            }
            return field;
        }
    }

    public class Field
    {
        protected const string TEMPLATE_HEADER_FORMAT = "<TH class=\"header\"><xsl:value-of select=\"/movies/metadata/field[@name='{0}']/@label\"/></TH>";

        public Field(string name)
        	: this(name, string.Empty)
        {
        }

        public Field(string name, string format)
        {
            Name = name;
            Format = format;
            TemplateHeader = string.Format(TEMPLATE_HEADER_FORMAT, name);
        }

        public string Name { get; set; }
        public string DisplayName { get { return ResourceUtils.GetSection("template")[Name]; } }
        public string TemplateHeader { get; set; }
        public string TemplateValue { get; set; }
        public string Format { get; set; }

        public override string ToString()
        {
            return DisplayName;
        }
    }

    public class SimpleField : Field
    {
        protected const string TEMPLATE_VALUE_FORMAT = "<TD class=\"value\"><xsl:value-of select=\"{0}\"/></TD>";

        public SimpleField(string name)
            : this(name, string.Empty)
        {
        }

        public SimpleField(string name, string format)
            : base(name, format)
        {
            TemplateValue = string.Format(TEMPLATE_VALUE_FORMAT, name);
        }
    }

    public class BooleanField : Field
    {
        protected const string TEMPLATE_VALUE_FORMAT = "<TD class=\"value\"><xsl:choose><xsl:when test=\"{0} = 'true'\"><xsl:text>{1}</xsl:text></xsl:when><xsl:otherwise><xsl:text>{2}</xsl:text></xsl:otherwise></xsl:choose></TD>";

        public BooleanField(string name)
            : this(name, string.Empty)
        {
        }

        public BooleanField(string name, string format)
            : base(name, format)
        {
        	TemplateValue = string.Format(TEMPLATE_VALUE_FORMAT, name, ResourceUtils.GetString("template", "true"), ResourceUtils.GetString("template", "false"));
        }
    }

    public class ListField : Field
    {
        protected const string TEMPLATE_VALUE_FORMAT = "<TD class=\"value\"><xsl:for-each select=\"{0}/{1}\"><xsl:value-of select=\"node()\"/><xsl:if test=\"position()!=last()\"><xsl:text>; </xsl:text></xsl:if></xsl:for-each></TD>";

        public ListField(string name, string singularName)
            : this(name, singularName, string.Empty)
        {
        }

        public ListField(string name, string singularName, string format)
            : base(name, format)
        {
            SingularName = singularName;
            TemplateValue = string.Format(TEMPLATE_VALUE_FORMAT, name, singularName);
        }

        public string SingularName { get; set; }
    }

    public class Column
    {
        public Column(Field field)
        {
            Field = field;
        }

        public Column(Field field, int width)
            : this(field)
        {
            Width = width;
        }

        public Field Field { get; set; }
        public int Width { get; set; }
        
        public string DataPropertyName
        {
        	get
        	{
        		if (Field != null)
        		{
        			return (Field is ListField) ? Field.Name + "asstring" : Field.Name;
        		}
        		return string.Empty;
        	}
        }
    }
}
